package com.qnnu.studenttravelsystem.interceptor;

import com.qnnu.studenttravelsystem.context.UserContext;
import com.qnnu.studenttravelsystem.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * JWT 拦截器 —— 相当于“小卖部门口的专职保安”
 *
 * 原理：
 * - 所有请求进门先过保安这关
 * - 保安检查会员卡（Token）
 * - 有效就写便签（存用户ID），无效就拦下
 */
@Component
public class JwtInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtUtil jwtUtil; // 保安配的验钞机

    /**
     * 顾客进门时检查（每个请求都会调用）
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 1. 登录柜台不用查卡（放行登录接口）
        // 因为你拦截他就生成不了token了
        if (request.getRequestURI().startsWith("/api/auth")) {
            return true;
        }

        // 2. 顾客必须出示会员卡（Header 中带 Authorization）
        String authHeader = request.getHeader("Authorization");
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 未授权
            return false;
        }

        // 3. 提取会员卡（去掉 "Bearer " 前缀）
        String token = authHeader.substring(7);

        // 4. 保安用验钞机验证会员卡
        if (!jwtUtil.validateToken(token)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        // 5. 验证成功！保安写便签：“这是用户ID=xxx”
        Long userId = jwtUtil.getUserIdFromToken(token);
        UserContext.setCurrentUserId(userId);

        // 6. 放行！让顾客去找收银员
        return true;
    }

    /**
     * 顾客离开后，撕掉便签（清理资源）
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserContext.clear(); // 防止ThreadLocal内存泄漏
        //所谓的内促泄露就是说：已经不再使用的对象，由于某种原因，其占用的内存无法被程序的垃圾回收机制（Garbage Collector, GC）回收。
        //这种情况会导致程序运行时间越长，占用的内存就越多。最终，可能会耗尽所有可用内存，导致程序崩溃（抛出 OutOfMemoryError）。
    }


}
